#ifndef __BUFFER__
#define __BUFFER__

#include <iostream>
#include <string>
#include <mutex>
#include <vector>
#include <thread>

namespace log_p
{
    // 用于解决主程序打印日志时，由于要进行IO将会导致效率下降，并且可能造成的send堵塞
    // buffer用于为日志器提供缓冲区
    // 将日志分开会增添写入次数，所以需要将日志统一一次输出
    // 缓冲区采用vector，不用string是每段日志都存在‘\n’,遇到就会结束;其次如果做成string

#define BASE_SIZE_BUFFER (100 * 1024 * 1024) // 基础缓冲区大小
// #define INCREASE_SIZE (1 * 1024 * 1024)     // 增长速率
#define MAX_SIZE_BUFFER (15 * 1024 * 1024) // 缓冲区最大阈值

    class buffer
    {
    public:
        buffer()
            : _buffer(BASE_SIZE_BUFFER)
        {
            _write_cur = 0;
            _read_cur = 0;
        }

        // 向缓冲区写入数据; 返回值：-1，错误; 0,缓冲区满，请重复; 大于0,表示写入字符量
        // 如果缓冲区满了，则返回0,由外部进行阻塞
        size_t push(const std::string &str)
        {
            if (_write_cur + str.size() >= _buffer.size())
            {
                if (_write_cur + str.size() < MAX_SIZE_BUFFER)
                    _buffer.resize(_write_cur + str.size());
                else
                    return 0;
            }
            std::copy(str.begin(), str.begin() + str.size(), _buffer.begin() + _write_cur);
            _write_cur += str.size();
            return _write_cur;
        }

        // 获取写入缓冲区下标位
        size_t GetWriteCur() { return _write_cur; }

        // 获取写入小标位指针
        char *GetWritePointer() { return &_buffer[_write_cur - 1]; }

        // 获取读出小标位指针
        char *GetReadPointer() { return &_buffer[_read_cur]; }

        // 向后偏移读缓冲区。
        void movereader(size_t length) {}

        // 析构用于检测缓冲区中是否还有数据
        bool IsOK()
        {
            if (_write_cur == 0 && _read_cur == 0)
                return true;
            return false;
        }
        // 获取剩余空间大小
        size_t GetAbleSize() { return _buffer.size() - _write_cur; }

        void ReSet()
        {
            _write_cur = 0;
            _read_cur = 0;
        }

        // 对缓冲区进行交换
        bool swap(buffer &bu)
        {
            _buffer.swap(bu._buffer);
            std::swap(_write_cur, bu._write_cur);
            std::swap(_read_cur, bu._read_cur);
            ReSet();
            return true;
        }

    private:
        // 偏移读出缓冲区下标位
        void ret_read_cur(size_t length)
        {
        }

    private:
        std::vector<char> _buffer; // 缓冲区(生产者的输入缓冲区; 消费者的输出缓冲区)
        size_t _write_cur;         // 写入缓冲区下标位
        size_t _read_cur;          // 读出缓冲区下标位

        std::mutex pro_mutex;       // 生产者关系锁,消费者不设置锁，一般分配一个线程即可
        std::thread _buffer_thread; // 用于服务日志输出的先出
    };

}

#endif